package myLearnjdk.jdk.reflect;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

/**
 * 动态编译
 * @author yangcheng  
 * @date 2019年1月23日  
 * @version V1.0
 */
public class DynamicCompile {
	public static void main(String[] args) throws Exception {
		/**
		 * 动态编译
		 * 标准文件管理器JavaCompiler有两个用途：1 用于自定义编译器如何读取和写入文件的基本构建块 2 在多个编译任务之间共享
		 * 
		 */
		JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
		/**
		 * 将.java文件编译生成.class文件
		 */
		int i=javaCompiler.run(null, null, null, "d:/Hello.java");
		System.out.println(i== 0 ? "编译成功！" : "编译失败！");
		
		/**
		 * 调用编译成功的可执行类（前提是类已经编译生成了.class文件）
		 */
		/**
		 * 第一种方式 通过Runtime执行
		 */
		try {
			Process process =Runtime.getRuntime().exec("java -cp d:/ Hello");
			BufferedReader reader=new BufferedReader(new InputStreamReader(process.getInputStream()));
			String str = null;
			while((str = reader.readLine() ) != null){
				System.out.println(str);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		/**
		 * 第二种方式
		 */
		URL[] urls = new URL[] {new URL("file:/"+"d:/")};
		URLClassLoader loader = new URLClassLoader(urls);
		Class c = loader.loadClass("myLearnjdk.jdk.reflect.assist.Hello");
        //调用加载类的main方法
        Method m = c.getMethod("main",String[].class);
        m.setAccessible(true);
		m.invoke(null, (Object)new String[]{});
	    //由于可变参数是JDK5.0之后才有。
	    //m.invoke(null, (Object)new String[]{});会编译成:m.invoke(null,"aa","bb"),就发生了参数个数不匹配的问题。
	    //因此，必须要加上(Object)转型，避免这个问题。
	}

}
